﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MSpecLauncher.Services;
using System.IO;
using MSpecLauncher.Model;

namespace MSpecLauncher
{
    public partial class MainForm : Form
    {
        // Filters to load different kind of files
        private const string CONFIG_FILE_FILTER = "Config files|*.conf|All files|*.*";
        private const string RESULT_FILE_FILTER = "XML files|*.xml|All files|*.*";

        // When a change is automatically detected, we can wait for more changes to process in the same event
        private const int WAIT_FOR_MORE_CHANGES_MS = 2000;

        private const int IMG_BALL_GRAY = 1;
        private const int IMG_BALL_RED = 2;
        private const int IMG_BALL_YELLOW = 3;
        private const int IMG_BALL_GREEN = 4;

        #region Grid columns names

        private const string COL_SUMM_STATUS_COLOR = "colSummaryStatusColor";
        private const string COL_SUMM_STATUS_INFO = "colSummaryStatusInfo";
        private const string COL_SUMM_ASSEMBLY = "colSummaryAssembly";
        private const string COL_SUMM_SUBJECT = "colSummarySubject";
        private const string COL_SUMM_CONTEXT_COUNT = "colSummaryContextsCount";
        private const string COL_SUMM_SPEC_COUNT = "colSummarySpecsCount";
        private const string COL_SUMM_SPEC_OK_COUNT = "colSummarySpecsPassedCount";
        private const string COL_SUMM_DURATION = "colSummaryDuration";
        private const string COL_SPEC_STATUS_COLOR = "colStatusColor";
        private const string COL_SPEC_STATUS_INFO = "colStatusInfo";
        private const string COL_SPEC_SUBJECT = "colSubject";
        private const string COL_SPEC_CONTEXT = "colContext";
        private const string COL_SPEC_SPEC = "colSpec";
        private const string COL_SPEC_DURATION = "colDuration";
        private const string COL_SPEC_OUTPUT = "colOutput";

        #endregion

        #region Colors

        private Color ALTERNATING_ROW_COLOR = Color.FromArgb(247, 247, 247);
        private Color GRID_BG_COLOR = Color.FromArgb(243, 243, 243);
        private Color GRID_COLOR = Color.FromArgb(224, 224, 224);
        private Color SPEC_PASSED_COLOR = Color.FromArgb(168, 228, 141);
        private Color SPEC_FAILED_COLOR = Color.Red;
        private Color SPEC_IGNORED_COLOR = Color.Orange;
        private Color SPEC_NOT_IMPLEMENTED_COLOR = Color.FromArgb(192, 192, 0);
        private Color SPEC_OTHER_COLOR = Color.Gray;

        #endregion

        #region Text labels

        private const string TXT_WARNING_EXCEPT = "Hey look!";
        private const string TXT_ERROR_EXCEPT = "Ooops!";

        private const string TXT_TAB_SPEC_IMPERFECT = "(!)";
        private const string TXT_TAB_SPEC_TMPLT = "{0} ({1} ms)";

        private const string TXT_SUMM_DURATION = "{0} ms";
        private const string TXT_SUMM_SPEC_COUNT = "Specs: {0}";
        private const string TXT_SUMM_SPEC_PASSED = "Passed: {0}";
        private const string TXT_SUMM_SPEC_FAILED = "Failed: {0}";
        private const string TXT_SUMM_SPEC_IGNORED = "Ignored: {0}";
        private const string TXT_SUMM_SPEC_NOT_IMPL = "Not impl.: {0}";

        private const string TXT_COL_SUMM_STATUS_INFO = "Status";
        private const string TXT_COL_SUMM_ASSEMBLY = "Assembly";
        private const string TXT_COL_SUMM_SUBJECT = "Subject";
        private const string TXT_COL_SUMM_CONTEXT_COUNT = "#Contexts";
        private const string TXT_COL_SUMM_SPEC_COUNT = "#Specs";
        private const string TXT_COL_SUMM_SPEC_OK_COUNT = "#Specs OK";
        private const string TXT_COL_SUMM_DURATION = "Duration (ms)";

        private const string TXT_COL_SPEC_STATUS_INFO = "Status";
        private const string TXT_COL_SPEC_SUBJECT = "Subject";
        private const string TXT_COL_SPEC_CONTEXT = "Context";
        private const string TXT_COL_SPEC_SPEC = "Spec";
        private const string TXT_COL_SPEC_DURATION = "Duration (ms)";
        private const string TXT_COL_SPEC_OUTPUT = "Output";

        #endregion

        private ILauncher launcher = null;
        

        public MainForm(string configFile)
        {
            InitializeComponent();

            // Create services
            this.CompositionRoot();

            // Load initial config file if given
            this.LoadConfigFile(configFile);
        }

        /// <summary>
        /// Creates necessary services
        /// </summary>
        private void CompositionRoot()
        {
            IConfigBuilder configBuilder = new ConfigBuilder();
            ICommandRunner specRunner = new CommandRunner();
            IModelBuilder modelBuilder = new MSpecModelBuilder();

            // Detect assemblies changes waiting for multiple changes to occur, and executing update in background
            IAsyncTimer asyncTimer = new AsyncTimer(WAIT_FOR_MORE_CHANGES_MS);
            IFileChangesDetector changesDetector = new AsyncChangesDetector(asyncTimer);

            this.launcher = new Launcher(configBuilder, specRunner, modelBuilder, changesDetector);
            this.launcher.AutomaticRunFinished += new Action(launcher_AutomaticRunFinished);
        }

        private void LoadConfigFile(string configFile)
        {
            try
            {
                this.launcher.LoadConfigFile(configFile);
            }
            catch (Exception ex)
            {
                this.ManageException(ex);
            }
        }

        private void Run()
        {
            try
            {
                // Change cursor
                Cursor.Current = Cursors.WaitCursor;

                // Run specs and update model
                this.launcher.Run();

                // Show results
                this.UpdateUI(this.launcher.SpecRun);
            }
            catch (Exception ex)
            {
                this.ManageException(ex);
            }

            // Reset cursor
            Cursor.Current = Cursors.Default;
        }

        private void LoadResultFile(string xmlFileName)
        {
            try
            {
                // Load model
                this.launcher.LoadResultFile(xmlFileName);

                // Show results
                this.UpdateUI(this.launcher.SpecRun);
            }
            catch (Exception ex)
            {
                this.ManageException(ex);
            }
        }

        private void OpenFileWithDefaultApp(string fileName)
        {
            try
            {
                System.Diagnostics.Process.Start(fileName);
            }
            catch (Exception ex)
            {
                this.ManageException(ex);
            }
        }

        private void launcher_AutomaticRunFinished()
        {
            // An automatic run has been executed

            // We must update UI in main thread
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(() => this.LoadResultFile(this.launcher.ResultFileName)));
            }
            else
            {
                this.LoadResultFile(this.launcher.ResultFileName);
            }
        }

        /// <summary>
        /// Manages the given exception
        /// </summary>
        private void ManageException(Exception ex)
        {
            if (ex is ApplicationException)
            {
                // If the exception is thrown by us, show only the message
                MessageBox.Show(ex.Message, TXT_WARNING_EXCEPT, MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            else
            {
                // If it is another kind of exception, show all the info
                MessageBox.Show(ex.ToString(), TXT_ERROR_EXCEPT, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #region UI manipulation

        /// <summary>
        /// Updates the UI with the given info
        /// </summary>
        private void UpdateUI(SpecRun specRun)
        {
            if (specRun != null)
            {
                // Clean UI
                this.ClearUI();

                // Statistics in main tab
                lblTime.Text = specRun.Date;
                lblRunTime.Text = string.Format(TXT_SUMM_DURATION, specRun.DurationInMillis);
                lblSpecsCount.Text = string.Format(TXT_SUMM_SPEC_COUNT, specRun.SpecCount.ToString());
                lblSpecsPassed.Text = string.Format(TXT_SUMM_SPEC_PASSED, specRun.SpecPassed.ToString());
                lblSpecsFailed.Text = string.Format(TXT_SUMM_SPEC_FAILED, specRun.SpecFailed.ToString());
                lblSpecsIgnored.Text = string.Format(TXT_SUMM_SPEC_IGNORED, specRun.SpecIgnored.ToString());
                lblSpecsNotImplemented.Text = string.Format(TXT_SUMM_SPEC_NOT_IMPL, specRun.SpecNotImplemented.ToString());
                lblSpecsPassed.ForeColor = SPEC_PASSED_COLOR;
                lblSpecsFailed.ForeColor = SPEC_FAILED_COLOR;
                lblSpecsIgnored.ForeColor = SPEC_IGNORED_COLOR;
                lblSpecsNotImplemented.ForeColor = SPEC_NOT_IMPLEMENTED_COLOR;
                this.CustomizeSummaryGrid();

                // Process results
                foreach (AssemblySpecs assembly in specRun.Assemblies)
                {
                    // Create Tab for Assembly, indicating in title duration and error mark
                    int imageIndex = assembly.AllPerfect ? IMG_BALL_GREEN : IMG_BALL_RED;
                    string title = string.Format(TXT_TAB_SPEC_TMPLT, assembly.Name, assembly.DurationInMillis.ToString());
                    TabPage tab = this.CreateTab(title, imageIndex);
                    tabControl.TabPages.Add(tab);

                    // Inside every assembly we create a tab for every subject
                    TabControl tabsAssembly = this.CreateTabControl(tabControl.ImageList);
                    tab.Controls.Add(tabsAssembly);
                    tabsAssembly.Dock = DockStyle.Fill;

                    foreach (SpecSubject subject in assembly.Subjects)
                    {
                        // Show subject summary in main tab
                        this.AddSummaryRow(assembly, subject);

                        // Create specific Tab for the subject, indicating in title duration and error mark
                        imageIndex = subject.AllPerfect ? IMG_BALL_GREEN : IMG_BALL_RED;
                        title = string.Format(TXT_TAB_SPEC_TMPLT, subject.Name, subject.DurationInMillis.ToString());
                        TabPage tabSubject = this.CreateTab(title, imageIndex);
                        tabsAssembly.TabPages.Add(tabSubject);

                        // Create grid for the tab
                        DataGridView grid = this.CreateSpecsGrid();
                        tabSubject.Controls.Add(grid);
                        grid.Dock = DockStyle.Fill;

                        foreach (SpecContext context in subject.Contexts)
                        {
                            foreach (Spec spec in context.Specs)
                            {
                                this.AddSpecRow(grid, subject, context, spec);
                            }
                        }
                    }
                }
            }
        }

        private void ClearUI()
        {
            // Clear summary labels
            lblTime.Text = string.Empty;
            lblRunTime.Text = string.Empty;
            lblSpecsCount.Text = string.Empty;
            lblSpecsPassed.Text = string.Empty;
            lblSpecsFailed.Text = string.Empty;
            lblSpecsIgnored.Text = string.Empty;
            lblSpecsNotImplemented.Text = string.Empty;

            // Clear summary grid
            summaryGrid.Rows.Clear();

            // Dispose every grid and tab except mainTab
            foreach (TabPage tab in tabControl.TabPages)
            {
                if (tab == mainTab) continue;

                foreach (Control control in tab.Controls)
                {
                    control.Dispose();
                }
                tab.Controls.Clear();
                tab.Dispose();
            }

            // Remove all the tabs
            tabControl.TabPages.Clear();

            // Add again main tab
            tabControl.TabPages.Add(mainTab);
        }

        private TabControl CreateTabControl(ImageList imageList)
        {
            TabControl tabControl = new TabControl();
            tabControl.Appearance = TabAppearance.FlatButtons;
            tabControl.ImageList = imageList;

            return tabControl;
        }

        private TabPage CreateTab(string text, int? imageIndex)
        {
            // Create page with text
            TabPage page = new TabPage(text);

            // Set icon
            if (imageIndex != null) page.ImageIndex = imageIndex.Value;

            return page;
        }

        private void CustomizeSummaryGrid()
        {
            // Summary grid is created in design mode in the main tab,
            // but all its config is done by code

            // Colors
            summaryGrid.AlternatingRowsDefaultCellStyle.BackColor = ALTERNATING_ROW_COLOR;
            summaryGrid.BackgroundColor = GRID_BG_COLOR;
            summaryGrid.GridColor = GRID_COLOR;
            summaryGrid.BorderStyle = BorderStyle.Fixed3D;
            summaryGrid.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.None;
            summaryGrid.RowHeadersBorderStyle = DataGridViewHeaderBorderStyle.None;
            summaryGrid.RowTemplate.Height = 26;

            // Non editable
            summaryGrid.AllowUserToAddRows = false;
            summaryGrid.AllowUserToDeleteRows = false;
            summaryGrid.AllowUserToOrderColumns = false;

            // Columns
            this.AddSummaryGridColumns(summaryGrid);

            // Resize event
            summaryGrid.Resize += new EventHandler(summarygrid_Resize);
        }

        private DataGridView CreateSpecsGrid()
        {
            DataGridView grid = new DataGridView();

            // Colors
            grid.AlternatingRowsDefaultCellStyle.BackColor = ALTERNATING_ROW_COLOR;
            grid.BackgroundColor = GRID_BG_COLOR;
            grid.GridColor = GRID_COLOR;
            grid.BorderStyle = BorderStyle.Fixed3D;
            grid.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.None;
            grid.RowHeadersBorderStyle = DataGridViewHeaderBorderStyle.None;
            grid.RowTemplate.Height = 26;

            // Non editable
            grid.AllowUserToAddRows = false;
            grid.AllowUserToDeleteRows = false;
            grid.AllowUserToOrderColumns = false;

            // Columns
            this.AddSpecsGridColumns(grid);

            // Double-click event
            grid.CellDoubleClick += new DataGridViewCellEventHandler(specsgrid_CellDoubleClick);

            // Resize event
            grid.Resize += new EventHandler(specsgrid_Resize);

            return grid;
        }

        private void AddSummaryGridColumns(DataGridView grid)
        {
            // Remove previous columns
            grid.Columns.Clear();

            DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
            col.Name = COL_SUMM_STATUS_COLOR;
            col.Width = 35;
            col.Frozen = true;
            col.HeaderText = "";
            col.ReadOnly = true;
            grid.Columns.Add(col);

            col = new DataGridViewTextBoxColumn();
            col.Name = COL_SUMM_STATUS_INFO;
            col.Width = 50;
            col.Frozen = false;
            col.HeaderText = TXT_COL_SUMM_STATUS_INFO;
            col.ReadOnly = true;
            col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            grid.Columns.Add(col);

            col = new DataGridViewTextBoxColumn();
            col.Name = COL_SUMM_ASSEMBLY;
            col.Width = 200;
            col.Frozen = false;
            col.HeaderText = TXT_COL_SUMM_ASSEMBLY;
            col.ReadOnly = true;
            grid.Columns.Add(col);

            col = new DataGridViewTextBoxColumn();
            col.Name = COL_SUMM_SUBJECT;
            col.Width = 200;
            col.Frozen = false;
            col.HeaderText = TXT_COL_SUMM_SUBJECT;
            col.ReadOnly = true;
            grid.Columns.Add(col);

            col = new DataGridViewTextBoxColumn();
            col.Name = COL_SUMM_CONTEXT_COUNT;
            col.Width = 80;
            col.Frozen = false;
            col.HeaderText = TXT_COL_SUMM_CONTEXT_COUNT;
            col.ReadOnly = true;
            col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            grid.Columns.Add(col);

            col = new DataGridViewTextBoxColumn();
            col.Name = COL_SUMM_SPEC_COUNT;
            col.Width = 80;
            col.Frozen = false;
            col.HeaderText = TXT_COL_SUMM_SPEC_COUNT;
            col.ReadOnly = true;
            col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            grid.Columns.Add(col);

            col = new DataGridViewTextBoxColumn();
            col.Name = COL_SUMM_SPEC_OK_COUNT;
            col.Width = 80;
            col.Frozen = false;
            col.HeaderText = TXT_COL_SUMM_SPEC_OK_COUNT;
            col.ReadOnly = true;
            col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            grid.Columns.Add(col);

            col = new DataGridViewTextBoxColumn();
            col.Name = COL_SUMM_DURATION;
            col.Width = 80;
            col.Frozen = false;
            col.HeaderText = TXT_COL_SUMM_DURATION;
            col.ReadOnly = true;
            col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            grid.Columns.Add(col);

            this.SetGridColumnWidth(grid, grid.Columns[COL_SUMM_SUBJECT]);
        }

        private void AddSpecsGridColumns(DataGridView grid)
        {
            DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
            col.Name = COL_SPEC_STATUS_COLOR;
            col.Width = 35;
            col.Frozen = true;
            col.HeaderText = "";
            col.ReadOnly = true;
            grid.Columns.Add(col);

            col = new DataGridViewTextBoxColumn();
            col.Name = COL_SPEC_STATUS_INFO;
            col.Width = 90;
            col.Frozen = false;
            col.HeaderText = TXT_COL_SPEC_STATUS_INFO;
            col.ReadOnly = true;
            grid.Columns.Add(col);

            col = new DataGridViewTextBoxColumn();
            col.Name = COL_SPEC_SUBJECT;
            col.Width = 200;
            col.Frozen = false;
            col.HeaderText = TXT_COL_SPEC_SUBJECT;
            col.ReadOnly = true;
            grid.Columns.Add(col);

            col = new DataGridViewTextBoxColumn();
            col.Name = COL_SPEC_CONTEXT;
            col.Width = 250;
            col.Frozen = false;
            col.HeaderText = TXT_COL_SPEC_CONTEXT;
            col.ReadOnly = true;
            grid.Columns.Add(col);

            col = new DataGridViewTextBoxColumn();
            col.Name = COL_SPEC_SPEC;
            col.Width = 300;
            col.Frozen = false;
            col.HeaderText = TXT_COL_SPEC_SPEC;
            col.ReadOnly = true;
            grid.Columns.Add(col);

            col = new DataGridViewTextBoxColumn();
            col.Name = COL_SPEC_DURATION;
            col.Width = 90;
            col.Frozen = false;
            col.HeaderText = TXT_COL_SPEC_DURATION;
            col.ReadOnly = true;
            col.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            grid.Columns.Add(col);

            col = new DataGridViewTextBoxColumn();
            col.Name = COL_SPEC_OUTPUT;
            col.Width = 100;
            col.Frozen = false;
            col.HeaderText = TXT_COL_SPEC_OUTPUT;
            col.ReadOnly = true;
            grid.Columns.Add(col);
        }

        private void AddSummaryRow(AssemblySpecs assembly, SpecSubject subject)
        {
            summaryGrid.Rows.Add();
            DataGridViewRow row = summaryGrid.Rows[summaryGrid.Rows.Count - 1];

            int specCount = 0;
            int passedCount = 0;
            subject.GetSpecsCount(out specCount, out passedCount);

            // Status color and tooltip
            row.Cells[COL_SUMM_STATUS_COLOR].Style.BackColor =
                specCount == passedCount ? Color.FromArgb(168, 228, 141) : Color.Orange;

            // Dont change status color when selected
            row.Cells[COL_SUMM_STATUS_COLOR].Style.SelectionBackColor = row.Cells[COL_SUMM_STATUS_COLOR].Style.BackColor;

            // Status text
            row.Cells[COL_SUMM_STATUS_INFO].Value = decimal.Round((passedCount / (decimal)specCount * 100), 1).ToString() + " %";
            
            // Assembly
            row.Cells[COL_SUMM_ASSEMBLY].Value = assembly.Name;

            // Subject
            row.Cells[COL_SUMM_SUBJECT].Value = subject.Name;

            // #Contexts
            row.Cells[COL_SUMM_CONTEXT_COUNT].Value = subject.ContextsCount;

            // #Specs
            row.Cells[COL_SUMM_SPEC_COUNT].Value = specCount;

            // #Specs OK
            row.Cells[COL_SUMM_SPEC_OK_COUNT].Value = passedCount;

            // #Duration
            row.Cells[COL_SUMM_DURATION].Value = subject.DurationInMillis;
        }

        private void AddSpecRow(DataGridView grid, SpecSubject subject, SpecContext context, Spec spec)
        {
            grid.Rows.Add();
            DataGridViewRow row = grid.Rows[grid.Rows.Count - 1];

            // Status color and tooltip
            row.Cells[COL_SPEC_STATUS_COLOR].Style.BackColor =
                spec.Status == ESpecStatus.Failed ? SPEC_FAILED_COLOR:
                spec.Status == ESpecStatus.Ignored ? SPEC_IGNORED_COLOR :
                spec.Status == ESpecStatus.NotImplemented ? SPEC_NOT_IMPLEMENTED_COLOR :
                spec.Status == ESpecStatus.Passed ? SPEC_PASSED_COLOR : SPEC_OTHER_COLOR;
            row.Cells[COL_SPEC_STATUS_COLOR].ToolTipText = spec.Status.ToString();

            // Dont change status color when selected
            row.Cells[COL_SPEC_STATUS_COLOR].Style.SelectionBackColor = row.Cells[COL_SPEC_STATUS_COLOR].Style.BackColor;

            // Status text
            row.Cells[COL_SPEC_STATUS_INFO].Value = spec.Status.ToString();

            // Subject
            row.Cells[COL_SPEC_SUBJECT].Value = subject.Name;

            // Context
            row.Cells[COL_SPEC_CONTEXT].Value = context.Name;

            // Spec
            row.Cells[COL_SPEC_SPEC].Value = spec.Name;

            // Duration
            row.Cells[COL_SPEC_DURATION].Value = spec.DurationInMillis.ToString();

            // Output
            row.Cells[COL_SPEC_OUTPUT].Value = spec.Output;

            // Add spec to the row tag
            row.Tag = spec;
        }

        private void specsgrid_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            DataGridView grid = sender as DataGridView;

            if (sender != null)
            {
                // Check if there is a valid row
                if (e.RowIndex >= 0 && e.RowIndex < grid.Rows.Count)
                {
                    // Get row Spec
                    Spec spec = grid.Rows[e.RowIndex].Tag as Spec;
                    if (spec != null)
                    {
                        if (spec.SpecErrors.Count() > 0)
                        {
                            // Show errors
                            StringBuilder sb = new StringBuilder("");
                            foreach (SpecError error in spec.SpecErrors)
                            {
                                sb.Append(error.Type + Environment.NewLine + error.Message + Environment.NewLine +
                                    error.StackTrace + Environment.NewLine + Environment.NewLine);
                            }

                            TextForm tForm = new TextForm(sb.ToString());
                            tForm.ShowDialog();
                        }
                    }
                }
            }
        }

        private void summarygrid_Resize(object sender, EventArgs e)
        {
            DataGridView grid = sender as DataGridView;

            if (sender != null) this.SetGridColumnWidth(grid, grid.Columns[COL_SUMM_SUBJECT]);
        }

        private void specsgrid_Resize(object sender, EventArgs e)
        {
            DataGridView grid = sender as DataGridView;

            if (sender != null) this.SetGridColumnWidth(grid, grid.Columns[COL_SPEC_SPEC]);
        }

        private void SetGridColumnWidth(DataGridView grid, DataGridViewColumn col)
        {
            if (grid.Columns.Count > 0)
            {
                int minWidth = 100;

                // Calculate width of all the columns
                int colWidths = 0;
                for (int i = 0; i < grid.Columns.Count; i++)
                {
                    colWidths += grid.Columns[i].Width;
                }
                colWidths = colWidths + grid.RowHeadersWidth - col.Width;

                // Resize columns width
                int nuevoAncho = grid.Width - colWidths - 20;
                if (nuevoAncho >= minWidth) col.Width = nuevoAncho;
                else col.Width = minWidth;
            }
        }

        #endregion


        #region UI Events

        private void btnLoadConfig_Click(object sender, EventArgs e)
        {
            // Show open file dialog
            openFileDialog.Filter = CONFIG_FILE_FILTER;
            DialogResult dr = openFileDialog.ShowDialog();
            if (dr == DialogResult.OK)
            {
                // Load selected config file
                string configFile = openFileDialog.FileName;
                this.LoadConfigFile(configFile);
            }
        }

        private void btnLoadResultFile_Click(object sender, EventArgs e)
        {
            // Show open file dialog
            openFileDialog.Filter = RESULT_FILE_FILTER;
            DialogResult dr = openFileDialog.ShowDialog();
            if (dr == DialogResult.OK)
            {
                // Load selected results file
                string resultFile = openFileDialog.FileName;
                this.LoadResultFile(resultFile);
            }
        }

        private void btnRun_Click(object sender, EventArgs e)
        {
            this.Run();
        }

        private void btnShowHTML_Click(object sender, EventArgs e)
        {
            // Get html file name
            string htmlFileName = this.launcher.HTMLFileName;

            if (!string.IsNullOrEmpty(htmlFileName))
            {
                // Open file with defautl app
                this.OpenFileWithDefaultApp(htmlFileName);
            }
        }

        private void btnShowXML_Click(object sender, EventArgs e)
        {
            // Get xml file name
            string xmlFileName = this.launcher.ResultFileName;

            if (!string.IsNullOrEmpty(xmlFileName))
            {
                // Open file with defautl app
                this.OpenFileWithDefaultApp(xmlFileName);
            }
        }

        #endregion


    }
}
